#AES,DES,MD5,base64,凯撒，维吉尼亚,栅栏密码,RSA,生成大素数 OK,
import tkinter as tk
from tkinter import messagebox, StringVar,filedialog
from tkinter import scrolledtext, ttk
import pyperclip  # 用于剪贴板功能
import base64
import time
from Crypto.Cipher import DES,AES
from Crypto.Util.Padding import pad, unpad
from md5 import MD5
from Crypto.PublicKey import RSA
from aes import AESCipher
from des import DESCipher
from rsa import RSACipher
from Classical import ClassicalCipher
from prime import Prime
from morse import Morse

# 主窗口
root = tk.Tk()
root.title("tingxli密码算法集成系统")
root.iconbitmap("favicon.ico")
root.geometry("800x600")
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)

# 左侧输入框和右侧输出框
frame_left = tk.Frame(root)
frame_left.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
frame_left.rowconfigure(1, weight=1)

frame_right = tk.Frame(root)
frame_right.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
frame_right.rowconfigure(1, weight=1)

# 明文/密文输入区域
label_input = tk.Label(frame_left, text="明/密文",font=('SimSun', 15))
label_input.pack(anchor="s")

input_text = scrolledtext.ScrolledText(frame_left, wrap=tk.WORD)
input_text.pack(fill="both", expand=True)

# 从剪切板获取
def get_from_clipboard():
    try:
        clipboard_text = pyperclip.paste()
        input_text.delete(1.0, tk.END)
        input_text.insert(tk.END, clipboard_text)
    except Exception as e:
        messagebox.showerror("错误", f"无法从剪贴板获取内容: {e}")

get_clipboard_button = tk.Button(frame_left, text="从剪切板获取", command=get_from_clipboard)
get_clipboard_button.pack(anchor="se", pady=5,after=label_input)  # 将按钮放置在右上角

# 输出结果区域
label_output = tk.Label(frame_right, text="输出结果",font=('SimSun', 16))
label_output.pack(anchor="s")

output_text = scrolledtext.ScrolledText(frame_right, wrap=tk.WORD)
output_text.pack(fill="both", expand=True)

# 复制到剪切板
def copy_to_clipboard():
    try:
        clipboard_text = output_text.get(1.0, tk.END).strip()
        pyperclip.copy(clipboard_text)
        messagebox.showinfo("提示", "输出结果已复制到剪贴板")
    except Exception as e:
        messagebox.showerror("错误", f"无法复制到剪贴板: {e}")

copy_clipboard_button = tk.Button(frame_right, text="复制到剪贴板", command=copy_to_clipboard)
copy_clipboard_button.pack(anchor="se", pady=5,after=label_output)  # 将按钮放置在右上角

# 下方控制区域
control_frame = tk.Frame(root)
control_frame.grid(row=1, column=0, columnspan=2, pady=10, sticky="ew")
control_frame.columnconfigure(1, weight=1)

global_file_path=None
# RSA文件选择按钮
def choose_rsa_file():
    global global_file_path 
    file_path= filedialog.askopenfilename(title="选择RSA密钥文件", filetypes=(("Text Files", "*.txt"), ("All Files", "*.*")))
    if file_path:
        try:
            rsaa = RSACipher()
            rsa_values = rsaa.read_to_decrypt(file_path)
            # 显示p,q内容在 GUI 中
            input_text.delete(1.0, tk.END)
            input_text.insert(1.0,rsa_values)
            # 可以在这里将 rsa 对象存储到一个全局变量，以便后续加解密使用
            global_file_path=file_path
        except Exception as e:
            messagebox.showerror("错误", f"读取文件失败: {e}")

choose_file_button = tk.Button(control_frame, text="添加文件", command=choose_rsa_file)
choose_file_button.grid(row=0, column=4, padx=5, pady=5)
# 密钥输入
label_key = tk.Label(control_frame, text="密钥")
label_key.grid(row=1, column=0, padx=5, pady=5, sticky="w")
key_entry = tk.Entry(control_frame)
key_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew")

# 加密类型选择
label_cipher_type = tk.Label(control_frame, text="密码类型")
label_cipher_type.grid(row=1, column=2, padx=5, pady=5, sticky="w")

cipher_type = StringVar()
cipher_dropdown = ttk.Combobox(control_frame, textvariable=cipher_type)
cipher_dropdown['values'] = ["Base64", "凯撒密码", "维吉尼亚密码", "栅栏密码","摩斯密码","MD5","AES", "DES", "RSA","生成两个大素数" ]
cipher_dropdown.grid(row=1, column=3, padx=5, pady=5, sticky="ew")
cipher_dropdown.current(0)  # 默认选择第一个选项


# 添加时间显示标签
dur_time_label = tk.Label(control_frame, text="耗时: ", font=('SimSun', 12))
dur_time_label.grid(row=2, column=0, columnspan=2, padx=5, pady=5, sticky="w")

# 更新耗时标签的函数
def update_dur_time(start_time, end_time):
    duration = end_time - start_time
    dur_time_label.config(text=f"耗时: {duration:.4f} 秒")

# 加密和解密功能
def encrypt():
    start_time=time.time()
    text = input_text.get(1.0, tk.END).strip()
    key = key_entry.get().strip()
    if not text:
        messagebox.showwarning("警告", "输入框不能为空")
        return
    if cipher_type.get() == "Base64":
        try:
            encoded = base64.b64encode(text.encode()).decode()
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    elif cipher_type.get()=="MD5":
        try:
            MD5_instance=MD5(text)
            MD5_instance.fill_text()
            encoded=MD5_instance.group_processing()
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    elif cipher_type.get()=="AES":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        aes_cipher=AESCipher(key)
        try:
            encoded=aes_cipher.encrypt(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    elif cipher_type.get()=="DES":#有点问题
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            des_cipher=DESCipher(key)
            encoded=des_cipher.des_encrypt(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    elif cipher_type.get()=="凯撒密码":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            Caesar=ClassicalCipher(key)
            encoded=Caesar.Encryp_cipher(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    elif cipher_type.get()=="维吉尼亚密码":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            Virginia=ClassicalCipher(key)
            encoded=Virginia.Encryp_Subcipher(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    elif cipher_type.get()=="栅栏密码":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            RailFence=ClassicalCipher(key)
            encoded=RailFence.fun_enCrypto(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    elif cipher_type.get() == "RSA":
        if not key:
            messagebox.showwarning("警告", "请输入RSA公钥e")
            return
        try:
            # 创建 RSACipher 实例并加载密钥文件
            rsa = RSACipher()
            #rsa.load_keys_from_file(key)  # key 是用户选择的 RSA 密钥文件路径
            rsa_values = rsa.read_to_decrypt(global_file_path)
            p, q,m = (rsa_values.get(key) for key in ('p', 'q','m'))
            n = p * q
            phi = (p - 1) * (q - 1)
            #e = rsa.generate_publickey(phi)
            e=int(key)#密钥框输入公钥
            d = rsa.get_reverse(e, phi)
            d=d+phi
            print(f"公钥: (e={e}, n={n})")
            print(f"私钥: (d={d}, n={n})")
            rsa.save_to_file(global_file_path, n=n, phi=phi, e=e, d=d)
            #m_input = input("输入明文信息（字母或数字）：")
            if isinstance(m,int):
                m = int(m)  # 如果输入的是数字，保持功能不变
                c = rsa.Encrypt_RSA(m, e, n)
                rsa.save_to_file(global_file_path,c=c)
                # 显示加密结果
                output_text.delete(1.0, tk.END)
                output_text.insert(tk.END, f"c={c}")
            else:
                # 明文块大小应小于 n 的长度（比如每个块最多50字符）
                encrypted_chunks = rsa.chunked_encrypt(m, e, n, 50)
                print(f"加密后的块: {encrypted_chunks}")
                rsa.save_to_file(global_file_path, encrypted_chunks=encrypted_chunks)
                # 显示加密结果
                output_text.delete(1.0, tk.END)
                output_text.insert(tk.END, f"ciphertext={encrypted_chunks}")

        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")

    elif cipher_type.get()=="生成两个大素数":
        if not key:
            messagebox.showwarning("警告", "bits不能为空 指定生成bit位素数")
            return
        key=int(key)
        if global_file_path:
            prime=Prime(key)
            p = prime.generate_large_prime(key)
            q = prime.generate_large_prime(key)
            print(f"生成的素数 p: {p}")
            print(f"生成的素数 q: {q}")
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, f"p={p}\nq={q}\n两个素数已经保存到指定目录:{global_file_path}")
            # 保存到文件
            prime.save_to_file(global_file_path, p=p, q=q)
        else:
            messagebox.showerror("错误", f"没有选择保存路径")
    elif cipher_type.get()=="摩斯密码":
        try:
            morse=Morse()
            encoded=morse.encrypt(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, encoded)
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {e}")
    else:
        messagebox.showinfo("提示", "其他加密算法尚未实现")
    end_time = time.time()
    #dur_time=end_time - start_time
    update_dur_time(start_time, end_time)  # 更新耗时标签

def decrypt():
    start_time=time.time()
    text = input_text.get(1.0, tk.END).strip()
    key = key_entry.get().strip()
    if not text:
        messagebox.showwarning("警告", "输入框不能为空")
        return
    if cipher_type.get() == "Base64":
        try:
            decoded = base64.b64decode(text.encode()).decode()
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get()=="MD5":
        try:
            decoded=f"MD5不可逆"
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get()=="AES":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        aes_cipher=AESCipher(key)
        try:
            decoded=aes_cipher.decrypt(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get()=="DES":#有问题，12，13
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            des_cipher=DESCipher(key)
            decoded=des_cipher.des_decrypt(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get()=="凯撒密码":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            Caesar=ClassicalCipher(key)
            decoded=Caesar.Decryp_cipher(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get()=="维吉尼亚密码":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            Virginia=ClassicalCipher(key)
            decoded=Virginia.Decryp_Subcipher(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get()=="栅栏密码":
        if not key:
            messagebox.showwarning("警告", "密钥不能为空")
            return
        try:
            RailFence=ClassicalCipher(key)
            decoded=RailFence.fun_deCrypto(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get() =="RSA":
        if not key:
            messagebox.showwarning("警告", "请输入RSA公钥e")
            return
        try:
            # 读取密钥文件中的内容
            rsa = RSACipher()
            rsa_value = rsa.read_to_decrypt(global_file_path)
            d, n = (rsa_value.get(key) for key in ('d', 'n'))
            print("d=",d,"n=",n)
            c=rsa_value.get('c')
            if not c:
                encrypted_chunks = rsa_value.get('encrypted_chunks')  # 从文件读取加密块
                print("这里读完了chunks")
                print(encrypted_chunks)
                decrypted_message = rsa.chunked_decrypt(encrypted_chunks, d, n)
                decoded=decrypted_message
                print("这里对chunks完成了解密")
                print(f"解密后的明文字符: {decrypted_message}")
                
            else:
                decrypted = rsa.Decrypt_RSA(c, d, n)
                decoded=decrypted
                print(f"解密后的明文: {decrypted}")
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, f"m={decoded}")
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    elif cipher_type.get()=="生成两个大素数":
        if not key:
            messagebox.showwarning("警告", "bits不能为空 指定生成bit位的素数")
            return
        key=int(key)
        if global_file_path:
            prime=Prime(key)
            p = prime.generate_large_prime(key)
            q = prime.generate_large_prime(key)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, f"p={p}\nq={q}\n两个素数已经保存到指定目录:{global_file_path}")
            # 保存到文件
            prime.save_to_file(global_file_path, p=p, q=q)
        else:
            messagebox.showerror("错误", f"没有选择保存路径")
    elif cipher_type.get()=="摩斯密码":
        try:
            morse=Morse()
            decoded=morse.decrypt(text)
            output_text.delete(1.0, tk.END)
            output_text.insert(tk.END, decoded)
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {e}")
    else:
        messagebox.showinfo("提示", "其他解密算法尚未实现")
    end_time = time.time()
    #dur_time=end_time - start_time
    update_dur_time(start_time, end_time)  # 更新耗时标签
# 加密、解密、清空按钮
encrypt_button = tk.Button(control_frame, text="加密", command=encrypt)
encrypt_button.grid(row=0, column=0, padx=5, pady=5)

decrypt_button = tk.Button(control_frame, text="解密", command=decrypt)
decrypt_button.grid(row=0, column=1, padx=5, pady=5)

def reset_fields():
    input_text.delete(1.0, tk.END)
    output_text.delete(1.0, tk.END)
    key_entry.delete(0, tk.END)

reset_button = tk.Button(control_frame, text="重置", command=reset_fields)
reset_button.grid(row=1, column=5, padx=5, pady=5)

# 运行主窗口
root.mainloop()
